分類是什麼呢?也就是今天我有K種不同的類別,我得到一筆資料,依照他的特徵,我判斷這會是那一類的資料!
今天跟大家介紹的方式不牽涉機率,且是以兩元分類作為出發。也就是說我們現在輸出只有 1 與 -1,兩種可能,分別就代表兩個類別。
還記得在回歸問題的時候我們是怎麼預測的嗎?以最簡單的Curve Fitting這個例子來看,就是把我們最後算出來的 w 與新得到的資料 x ,做內積得到的值,就是我們的預測值。也就是預測值 y 是
那麼相當類似的,在分類中,我們也是用這個值,不過這此我們只取正負號,也就是
其中sign就是取這個式子的正負號的意思。
接著一樣是最小化error function,第一個中括號的意思我們先當作一個布林函數,也就是裡面的東西成立的時候為一,反之為零。
這樣的error function得到的值會是離散的,沒有辦法用微分來找最好的 w ,因此我們使用迭代的方式來找最好的 w 。
其中的 n 是只有那些目前的 w 分錯的 n 才要做更新。而中止條件就是全部的資料都分對。
為什麼是這樣呢?首先我們來看什麼是分錯,分錯有現在要輸出 1 你輸出 -1, 或現在要輸出 -1 你輸出 1,兩種情況。而我們所得到的輸出是用我們的 w 與 x 做內積得到的,也就是說當分錯的情況發生,就是我們內積所得到的值,太大或是太小。內積的大小其實隱含著兩個向量夾角大小的意思,內積越大,夾角越小;內積越小,夾角越大。
所以當今天要的是 1 我輸出 -1,表示我目前的 w 與這一筆資料的夾角太小了,要大一點,那就是很簡單的把 w 加上 x 。反之要 -1 我輸出 1,就是夾角太大了,要小一點,那我就把 w 減去 x。把它寫成寫成更新式就是
這個演算法我們叫做Perceptron learning algorithm( PLA ),不過這個演算法,它只能在線性可分的資料中有用,也就是如果你的資料沒辦法畫一刀分開的話,這個演算法永遠不會停。不過我們的式子中都有提到phi,也就是這邊一樣可以用之前使用過得轉換,讓我們的資料到其他空間,也就是說也許你的資料在單純的特徵空間分不開,可是他到其他的空間可以分開!
或是可以使用PLA的變形pocket演算法!他的概念跟PLA差不多,唯一不同的地方是在於,他要更新 w 的時候,會先確定更新後的 w ,會比更新前的 w 有更低的 error,也就是他要更新 w 之前會先算一次error,比現在低才更新。這樣一來只要迭代夠多次,就可以找到一個不錯的 w 來分資料了!
以下簡單實做PLA,資料前處理我是大概做一個能動的,建議大家可以去看一下前處理的套件,畢竟前處理真的滿煩的。資料集我是取自林軒田老師的作業資料集
import numpy as np
def phi(x): #簡單的加上一個常數項提供offset的能力
return np.insert(x, 0, 1.).reshape(5,1) #insert 1. at 0th index
train_data = []
train_tag = []
with open("train_data.txt" , "r") as infile:
for line in infile:
line = line.split('\n')[0]
data = line.split('\t')
tag = data[1]
data = data[0].split(' ')
train_data += [data]
train_tag += [tag]
train_data = np.asarray(train_data, dtype = float)
train_tag = np.asarray(train_tag, dtype = float)
w = np.zeros((5,1))
while True:
flag = True
for n in range(train_data.shape[0]):
if np.sign(w.T.dot(phi(train_data[n]))) != np.sign(train_tag[n]):
w += train_tag[n] * phi(train_data[n])
flag = False
if flag:
break
print w